import { Server } from '@modelcontextprotocol/sdk/server/index';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio';
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from '@modelcontextprotocol/sdk/types';
import * as fs from 'fs/promises';
import * as path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';
import puppeteer from 'puppeteer';
import { Logger } from '~/utils/logger';

/**
 * 设计图 MCP 服务器
 * 提供设计图相关的工具和资源访问
 */
export class DesignMcpServices {
  private server: Server;
  private designAssetsPath: string;
  private execAsync = promisify(exec);

  constructor() {
    this.server = new Server(
      {
        name: 'design-assets-server',
        version: '1.0.0',
      },
      {
        capabilities: {
          tools: {},
          resources: {},
        },
      }
    );

    this.designAssetsPath = path.join(process.cwd(), 'design-assets');
    this.setupHandlers();
  }

  private setupHandlers() {
    // 注册工具列表处理器
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: 'capture_design_from_url',
          description: '从网页链接捕获设计图资源',
          inputSchema: {
            type: 'object',
            properties: {
              url: {
                type: 'string',
                description: '设计图网页链接',
              },
              designId: {
                type: 'string',
                description: '保存的设计图ID',
              },
              captureOptions: {
                type: 'object',
                description: '捕获选项',
                properties: {
                  openBrowser: {
                    type: 'boolean',
                    description: '是否打开系统默认浏览器',
                    default: true,
                  },
                  waitForRequest: {
                    type: 'string',
                    description: '等待特定请求URL模式',
                    default: '**/api/**',
                  },
                  timeout: {
                    type: 'number',
                    description: '超时时间(秒)',
                    default: 30,
                  },
                },
              },
            },
            required: ['url', 'designId'],
          },
        },
        {
          name: 'get_design_data',
          description: '获取设计图数据和元信息',
          inputSchema: {
            type: 'object',
            properties: {
              designId: {
                type: 'string',
                description: '设计图ID',
              },
              includeAssets: {
                type: 'boolean',
                description: '是否包含资源文件信息',
                default: false,
              },
            },
            required: ['designId'],
          },
        },
        {
          name: 'list_design_assets',
          description: '列出所有设计图资源',
          inputSchema: {
            type: 'object',
            properties: {
              category: {
                type: 'string',
                description: '资源分类筛选',
                enum: ['ui', 'icon', 'illustration', 'all'],
              },
            },
          },
        },
      ],
    }));

    // 注册工具调用处理器
    this.server.setRequestHandler(CallToolRequestSchema, async request => {
      const { name, arguments: args } = request.params;
      try {
        switch (name) {
          case 'capture_design_from_url':
            return await this.handleCaptureDesignFromUrl(
              args.url as string,
              args.designId as string,
              args.captureOptions as any
            );
          case 'get_design_data':
            return await this.handleGetDesignData(
              args.designId as string,
              args.includeAssets as boolean
            );
          case 'list_design_assets':
            return await this.handleListDesignAssets(args.category as string);
          default:
            throw new McpError(ErrorCode.MethodNotFound, `未知工具: ${name}`);
        }
      } catch (error) {
        throw new McpError(
          ErrorCode.InternalError,
          `工具执行失败: ${error instanceof Error ? error.message : String(error)}`
        );
      }
    });
  }

  /**
   * 获取设计图信息
   */
  private async getDesignInfo(designId: string) {
    const designPath = path.join(this.designAssetsPath, `${designId}.json`);
    try {
      const data = await fs.readFile(designPath, 'utf-8');
      return JSON.parse(data);
    } catch (error) {
      throw new Error(`设计图 ${designId} 不存在或读取失败`);
    }
  }

  /**
   * 处理获取设计数据请求
   */
  private async handleGetDesignData(designId: string, includeAssets = false) {
    const designData = await this.getDesignInfo(designId);

    const result: any = {
      metadata: {
        id: designId,
        name: designData.name || designId,
        version: designData.version || '1.0.0',
        lastModified: designData.lastModified || new Date().toISOString(),
      },
      design: {
        width: designData.width || 1920,
        height: designData.height || 1080,
        nodes: designData.nodes || [],
        styles: designData.styles || {},
      },
    };

    if (includeAssets) {
      result.assets = await this.getDesignAssets(designId);
    }

    return {
      content: [
        {
          type: 'text',
          text: JSON.stringify(result, null, 2),
        },
      ],
    };
  }

  /**
   * 处理列出设计资源请求
   */
  private async handleListDesignAssets(category = 'all') {
    const assets = await this.listDesignAssets(category);

    return {
      content: [
        {
          type: 'text',
          text: JSON.stringify({ assets, total: assets.length }, null, 2),
        },
      ],
    };
  }

  /**
   * 获取设计资源文件
   */
  private async getDesignAssets(designId: string) {
    const assetsPath = path.join(this.designAssetsPath, designId, 'assets');
    try {
      const files = await fs.readdir(assetsPath);
      return files.map(file => ({
        name: file,
        path: path.join(assetsPath, file),
        type: path.extname(file).slice(1),
      }));
    } catch {
      return [];
    }
  }
  /**
   * 列出设计图资源
   */
  private async listDesignAssets(category = 'all') {
    try {
      const files = await fs.readdir(this.designAssetsPath);
      const designs = [];

      for (const file of files) {
        if (file.endsWith('.json')) {
          const designId = path.basename(file, '.json');
          try {
            const designData = await this.getDesignInfo(designId);
            const designCategory = designData.category || 'ui';

            if (category === 'all' || designCategory === category) {
              designs.push({
                id: designId,
                name: designData.name || designId,
                category: designCategory,
                thumbnail: designData.thumbnail || null,
                lastModified: designData.lastModified || null,
              });
            }
          } catch {
            // 跳过无效的设计文件
          }
        }
      }

      return designs;
    } catch {
      return [];
    }
  }

  /**
   * 处理从URL捕获设计图请求
   */
  private async handleCaptureDesignFromUrl(
    url: string,
    designId: string,
    options: any = {}
  ) {
    const {
      openBrowser = true,
      waitForRequest = '**/api/**',
      timeout = 30,
    } = options;

    try {
      // 1. 打开系统默认浏览器
      if (openBrowser) {
        await this.openUrlInBrowser(url);
      }

      // 2. 使用 Puppeteer 捕获网页请求
      const designData = await this.captureDesignData(
        url,
        waitForRequest,
        timeout
      );

      // 3. 保存设计数据
      await this.saveDesignData(designId, designData);

      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(
              {
                success: true,
                message: `设计图 ${designId} 已成功捕获并保存`,
                designId,
                capturedAt: new Date().toISOString(),
                dataSize: JSON.stringify(designData).length,
              },
              null,
              2
            ),
          },
        ],
      };
    } catch (error) {
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(
              {
                success: false,
                error: error instanceof Error ? error.message : String(error),
                designId,
              },
              null,
              2
            ),
          },
        ],
      };
    }
  }

  /**
   * 打开系统默认浏览器
   */
  private async openUrlInBrowser(url: string) {
    const platform = process.platform;
    let command: string;

    switch (platform) {
      case 'win32':
        command = `start "" "${url}"`;
        break;
      case 'darwin':
        command = `open "${url}"`;
        break;
      case 'linux':
        command = `xdg-open "${url}"`;
        break;
      default:
        throw new Error(`不支持的操作系统: ${platform}`);
    }

    await this.execAsync(command);
    console.log(`已在默认浏览器中打开: ${url}`);
  }

  /**
   * 使用 Puppeteer 捕获设计数据
   */
  private async captureDesignData(
    url: string,
    requestPattern: string,
    timeout: number
  ) {
    const browser = await puppeteer.launch({
      headless: true,
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
    });

    try {
      const page = await browser.newPage();
      const capturedRequests: any[] = [];

      // 监听网络请求
      page.on('response', async response => {
        const requestUrl = response.url();

        // 检查是否匹配请求模式
        if (this.matchesPattern(requestUrl, requestPattern)) {
          try {
            const responseData = await response.json();
            capturedRequests.push({
              url: requestUrl,
              status: response.status(),
              headers: response.headers(),
              data: responseData,
              timestamp: new Date().toISOString(),
            });
          } catch {
            // 非JSON响应，跳过
          }
        }
      }); // 访问页面
      await page.goto(url, {
        waitUntil: 'networkidle2',
        timeout: timeout * 1000,
      });

      // 等待一段时间确保所有请求完成
      await new Promise(resolve => setTimeout(resolve, 2000));

      if (capturedRequests.length === 0) {
        throw new Error(`未捕获到匹配模式 "${requestPattern}" 的请求`);
      }

      // 返回捕获的数据
      return {
        name: `设计图_${new Date().toISOString().split('T')[0]}`,
        version: '1.0.0',
        category: 'web-capture',
        sourceUrl: url,
        capturedAt: new Date().toISOString(),
        requests: capturedRequests,
        // 简化的设计数据结构
        nodes: this.extractDesignNodes(capturedRequests),
        styles: this.extractDesignStyles(capturedRequests),
      };
    } finally {
      await browser.close();
    }
  }

  /**
   * 检查URL是否匹配模式
   */
  private matchesPattern(url: string, pattern: string): boolean {
    // 简单的通配符匹配
    const regex = new RegExp(
      pattern.replace(/\*\*/g, '.*').replace(/\*/g, '[^/]*')
    );
    return regex.test(url);
  }

  /**
   * 从捕获的请求中提取设计节点
   */
  private extractDesignNodes(requests: any[]): any[] {
    const nodes: any[] = [];

    requests.forEach((request, index) => {
      if (request.data && typeof request.data === 'object') {
        // 尝试从响应数据中提取设计相关信息
        if (
          request.data.components ||
          request.data.frames ||
          request.data.elements
        ) {
          const components =
            request.data.components ||
            request.data.frames ||
            request.data.elements;
          if (Array.isArray(components)) {
            components.forEach((component, compIndex) => {
              nodes.push({
                id: `node_${index}_${compIndex}`,
                type: component.type || 'FRAME',
                name: component.name || `节点_${compIndex}`,
                x: component.x || 0,
                y: component.y || 0,
                width: component.width || 100,
                height: component.height || 100,
                ...component,
              });
            });
          }
        }
      }
    });

    return nodes;
  }

  /**
   * 从捕获的请求中提取设计样式
   */
  private extractDesignStyles(requests: any[]): any {
    const styles: any = {};

    requests.forEach(request => {
      if (request.data && request.data.styles) {
        Object.assign(styles, request.data.styles);
      }
    });

    return styles;
  }

  /**
   * 保存设计数据到文件
   */
  private async saveDesignData(designId: string, designData: any) {
    const designPath = path.join(this.designAssetsPath, `${designId}.json`);

    // 确保目录存在
    await fs.mkdir(this.designAssetsPath, { recursive: true });

    // 保存设计数据
    await fs.writeFile(
      designPath,
      JSON.stringify(designData, null, 2),
      'utf-8'
    );

    console.log(`设计数据已保存到: ${designPath}`);
  }

  /**
   * 启动服务器
   */
  async start() {
    const transport = new StdioServerTransport();

    await this.server.connect(transport);

    Logger.log('设计图 MCP 服务器已连接');
  }
}
